package com.egaleye.core.response;

import com.egaleye.core.exception.BaseException;
import org.springframework.http.ResponseEntity;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.StringJoiner;

/**
 * Restful接口响应数据结构
 *
 * @author tangkaijun
 * @version 2019/9/16 liubaoning
 * @since jdk1.8
 */
public class RestfulResponse<T> extends ResponseEntity {

	/**
	 * Restful接口响应体
	 */
	private RestfulBody<T> restfulBody;

	/**
	 * 构造函数
	 */
	public RestfulResponse() {
		this(CodeEnum.SUCCESS);
	}

	/**
	 * 构造函数
	 *
	 * @param data 返回数据
	 */
	public RestfulResponse(T data) {
		this(new RestfulBody<>(data), CodeEnum.SUCCESS);
	}

	/**
	 * 构造函数
	 *
	 * @param codeEnum codeEnum
	 */
	public RestfulResponse(CodeEnum codeEnum) {
		this(new RestfulBody<>(codeEnum), codeEnum);
	}

	/**
	 * 构造函数
	 *
	 * @param restfulBody 响应体
	 * @param codeEnum    业务状态码
	 */
	@SuppressWarnings("unchecked")
	private RestfulResponse(RestfulBody<T> restfulBody, CodeEnum codeEnum) {
		super(restfulBody, codeEnum != null ? codeEnum.getHttpStatus() : CodeEnum.SUCCESS.getHttpStatus());
		this.restfulBody = restfulBody;
	}

	/**
	 * 设置错误响应
	 *
	 * @param <T>      <T>
	 * @param codeEnum 错误码
	 * @return RestfulResponse<T>
	 */
	public static <T> RestfulResponse<T> error(CodeEnum codeEnum) {
		return new RestfulResponse<>(codeEnum);
	}

	/**
	 * 设置业务状态码
	 *
	 * @param codeEnum 业务状态码
	 * @return RestfulResponse<T>
	 */
	public RestfulResponse<T> code(CodeEnum codeEnum) {
		this.restfulBody.setCode(codeEnum.getCode());
		this.restfulBody.setMessage(codeEnum.getMessage());
		return this;
	}
	
	/**
	 * 设置业务状态码
	 *
	 * @param codeEnum 业务状态码
	 * @return RestfulResponse<T>
	 */
	public RestfulResponse<T> code(BaseException e, CodeEnum codeEnum) {
		this.restfulBody.setCode(e.getCodeEnum().getCode());
		this.restfulBody.setMessage(codeEnum.getMessage()+ e.getMessage());
		return this;
	}

	/**
	 * 设置业务状态码（不带“业务异常:”前缀）
	 * 
	 * @param e 异常信息
	 * @return RestfulResponse<T>
	 */
	public RestfulResponse<T> code(BaseException e) {
		this.restfulBody.setCode(e.getCodeEnum().getCode());
		this.restfulBody.setMessage(e.getCodeEnum().getMessage());
		return this;
	}

	/**
	 * 设置业务数据
	 *
	 * @param data data
	 * @return RestfulResponse<T>
	 */
	public RestfulResponse<T> data(T data) {
		this.restfulBody.setData(data);
		return this;
	}

	/**
	 * 设置提示信息
	 *
	 * @param message message
	 * @return this
	 */
	public RestfulResponse<T> message(Object... message) {
		this.restfulBody.setMessage(MessageFormat.format(getMessage(), message));
		return this;
	}

	/**
	 * @return 获取 code属性值
	 */
	public int getCode() {
		return this.restfulBody.getCode();
	}

	/**
	 * @return 获取 data属性值
	 */
	public T getData() {
		return this.restfulBody.getData();
	}

	/**
	 * @return 获取 message属性值
	 */
	public String getMessage() {
		return this.restfulBody.getMessage();
	}

	/**
	 * @return 获取 restfulBody属性值
	 */
	public RestfulBody<T> getRestfulBody() {
		return restfulBody;
	}

	/**
	 * @param restfulBody restfulBody
	 */
	public void setRestfulBody(RestfulBody<T> restfulBody) {
		this.restfulBody = restfulBody;
	}

	@Override
	public String toString() {
		return new StringJoiner(", ", RestfulResponse.class.getSimpleName() + "[", "]")
				.add("restfulBody=" + restfulBody)
				.toString();
	}

	/**
	 * Restful接口响应体
	 *
	 * @author liubaoning
	 * @version 2019/9/16 liubaoning
	 * @since jdk1.8
	 */
	public static class RestfulBody<R> implements Serializable {

		/**
		 * serialVersionUID
		 */
		private static final long serialVersionUID = -7115914438015603229L;

		/**
		 * 业务数据
		 */
		private R data;

		/**
		 * 业务响应码
		 */
		private int code;

		/**
		 * 提示信息
		 */
		private String message;

		/**
		 * 构造函数
		 *
		 * @param data 业务数据
		 */
		public RestfulBody(R data) {
			this(data, CodeEnum.SUCCESS);
		}

		/**
		 * 构造函数
		 *
		 * @param codeEnum 错误码
		 */
		public RestfulBody(CodeEnum codeEnum) {
			this(null, codeEnum);
		}

		/**
		 * 构造函数
		 *
		 * @param data     业务数据
		 * @param codeEnum 错误码
		 */
		public RestfulBody(R data, CodeEnum codeEnum) {
			this.data = data;
			this.code = codeEnum != null ? codeEnum.getCode() : CodeEnum.SUCCESS.getCode();
			this.message = codeEnum != null ? codeEnum.getMessage() : CodeEnum.SUCCESS.getMessage();
		}
		
		public RestfulBody(BaseException e) {
			this.data = null;
			this.code = e.getCodeEnum().getCode();
			this.message = e.getCodeEnum().getMessage();
		}

		/**
		 * 设置错误响应
		 *
		 * @param <R>      <R>
		 * @param codeEnum 错误码
		 * @return RestfulBody<R>
		 */
		public static <R> RestfulBody<R> error(CodeEnum codeEnum) {
			return new RestfulBody<>(codeEnum);
		}

		/**
		 * @return 获取 data属性值
		 */
		public R getData() {
			return data;
		}

		/**
		 * @return 获取 code属性值
		 */
		public int getCode() {
			return code;
		}

		public void setData(R data) {
			this.data = data;
		}

		public void setCode(int code) {
			this.code = code;
		}

		public void setMessage(String message) {
			this.message = message;
		}

		/**
		 * @return 获取 message属性值
		 */
		public String getMessage() {
			return message;
		}

		@Override
		public String toString() {
			return new StringJoiner(", ", RestfulBody.class.getSimpleName() + "[", "]")
					.add("data=" + data)
					.add("code=" + code)
					.add("message='" + message + "'")
					.toString();
		}
	}

}
